package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.user.mapper.UserInfoMapper;
import com.atguigu.tingshu.user.mapper.UserPaidAlbumMapper;
import com.atguigu.tingshu.user.mapper.UserPaidTrackMapper;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.aspectj.weaver.ast.Var;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private WxMaService wxMaService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private KafkaService kafkaService;

	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;

	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;

	@Override
	public Map<String, Object> wxLogin(String code) {
		//通过tocken  换取openid   每个微信用户对应唯一一个的openid
		String openId =null;
		try {
			//需要将当前这个用户的appid   secret传入系统中
			openId = wxMaService.jsCode2SessionInfo(code).getOpenid();
		} catch (WxErrorException e) {
			throw new RuntimeException(e);
		}
		//通过openid查询用户信息是否被注册过
		//select wx_open_id from user_info where wx_open_id = ''
		UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openId));
		//判断
		if (null == userInfo){
			//实现注册功能
			//创建用户对象
			userInfo = new UserInfo();
			//设置openid
			userInfo.setWxOpenId(openId);
			//设置昵称
			userInfo.setNickname("听友："+System.currentTimeMillis());
			userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
			//保存数据
			this.save(userInfo);
			//  初始化账户信息. userAccountFeignClient.initUserAccount(userInfo.getId(),100,100); 同步
			//  失败了? 你想回滚账户注册信息。本地事务解决不了；使用分布式事务！ seata;
			//  userAccountFeignClient.initUserAccount(userInfo.getId(),100,100);
			//  异步：能够提高效率，实现解耦. 发送消息需要传递的参数?
			//  参数一：topics 参数二：消息主体--消息内容是由消费者需求决定！
			kafkaService.sendMsg(KafkaConstant.QUEUE_USER_REGISTER,userInfo.getId().toString());
		}

		//不为空 注册过  返回token   并将数据放入缓存中
		String token = UUID.randomUUID().toString().replaceAll("-", "");
		//声明一个key来记录
		String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
		//将数据放入缓存中
		this.redisTemplate.opsForValue().set(loginKey,userInfo,RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
		//声明一个map
		Map<String,Object> map = new HashMap<>();
		//设置token
		map.put("token",token);
		//返回数据
		return map;
	}

	/**
	 * 根据用户id查询用户信息
	 * @param userId
	 * @return
	 */
	@Override
	public UserInfoVo getUserInfo(Long userId) {
		//select * from user_info where id = userId
		UserInfo userInfo = this.getById(userId);
		//判断用户信息是否为空
		if (null == userInfo){
			return null;
		}
		//进行属性拷贝
		//声明一个对象
		UserInfoVo userInfoVo = new UserInfoVo();
		BeanUtils.copyProperties(userInfo,userInfoVo);
		//返回数据
		return userInfoVo;
	}

	@Override
	public void updateUser(UserInfoVo userInfoVo, Long userId) {
		//修改用户信息
		//创建对象
		UserInfo userInfo = new UserInfo();
		//属性拷贝
		BeanUtils.copyProperties(userInfoVo,userInfo);
		//设置id
		userInfo.setId(userId);
		//调用修改方法
		this.updateById(userInfo);
	}

	/**
	 * 判断用户是否购买声音
	 *
	 * @param albumId     专辑Id
	 * @param trackIdList 需要收费的声音Id 列表;
	 * @param userId      用户Id
	 * @return
	 */
	@Override
	public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdList, Long userId) {
		//  查看用户是否购买过专辑，如果购买过专辑，则需要付费的声音Id集合都需要免费.user_paid_album
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getAlbumId, albumId).eq(UserPaidAlbum::getUserId, userId));
		//  判断是否为空
		if (null != userPaidAlbum) {
			//  处理数据 map中的key=trackId value=0或1 1：表示免费 0：表示付费。
			Map<Long, Integer> map = trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 1));
			//  trackIdList.stream().collect(Collectors.toMap(trackId-> trackId, trackId-> 1));
			//  返回数据
			return map;
		}
		//  判断用户是否购买过当前专辑的声音。user_paid_track
		//  select * from user_paid_track paid where user_id = ? and album_id = 1429 and track_id in (trackIdList);
		LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId).in(UserPaidTrack::getTrackId, trackIdList);
		//  获取到当前这个用户购买过的声音Id列表
		List<UserPaidTrack> userPaidTrackIdList = userPaidTrackMapper.selectList(wrapper);
		//  判断 trackIdList 这个集合中的声音Id 是否有购买过的声音Id.
		Map<Long, Integer> map = new HashMap<>();
		for (Long trackId : trackIdList) {
			//  判断当前集合是否为空
			if (CollectionUtils.isEmpty(userPaidTrackIdList)){
				map.put(trackId, 0);
			} else {
				//  判断userPaidTrackIdList 集合中是否包含trackId
				if (userPaidTrackIdList.contains(trackId)) {
					map.put(trackId, 1);
				} else {
					map.put(trackId, 0);
				}
			}
		}
		//  返回数据
		return map;
	}

	@Override
	public Boolean isPaidAlbum(Long userId, Long albumId) {
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(
				new LambdaQueryWrapper<UserPaidAlbum>()
						.eq(UserPaidAlbum::getUserId, userId)
						.eq(UserPaidAlbum::getAlbumId, albumId)
		);

		return null != userPaidAlbum;
	}

	@Override
	public List<Long> findUserPaidTrackList(Long userId, Long albumId) {
		// 根据用户Id 与 专辑Id 获取到已购买的声音集合
		List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
				.eq(UserPaidTrack::getUserId, userId)
				.eq(UserPaidTrack::getAlbumId, albumId));
		// 获取到已购买的声音集合Id 列表
		List<Long> trackIdList = userPaidTrackList
						.stream()
						.map(UserPaidTrack::getTrackId)
						.collect(Collectors.toList());
		// 返回集合数据
		return trackIdList;
	}

	/**
	 * 判断用户是否购买过声音
	 * @param userId
	 * @param trackIdList
	 * @return
	 */
	@Override
	public Boolean isPaidTrack(Long userId, List<Long> trackIdList) {
		//查询数据
		LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(UserPaidTrack::getUserId,userId);
		wrapper.in(UserPaidTrack::getTrackId,trackIdList);
		Long count = userPaidTrackMapper.selectCount(wrapper);
		return count > 0;
	}
}
